package Helpers;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import Annotations.AttributeNameAnnotation;
import Annotations.EntityNameAnnotation;
import Annotations.ValueObjectNameAnnotation;

public abstract class DBBackwardHelper {
	final private static String HasNoAnnotatedName = "HasNoAnnotatedName";

	public static final String TableSuffix = "_TABLE";

	public static String getAnnotatedFieldName(Field field)
			throws ClassNotFoundException {
		return getAnnotatedName(field.getAnnotations());
	}

	public static String getAnnotatedCollectionName(Field field)
			throws ClassNotFoundException {
		if (field.getAnnotations() == null) {
			return null;
		} else {
			for (Annotation annotation : field.getAnnotations()) {
				if (annotation.annotationType() == AttributeNameAnnotation.class) {
					AttributeNameAnnotation ana = (AttributeNameAnnotation) annotation;
					return ana.collectionTypeInDB();
				}
			}
		}
		return null;
	}

	public static String getAnnotatedClassName(Class recievedClass)
			throws ClassNotFoundException {
		return getAnnotatedName(recievedClass.getAnnotations());
	}

	public static String getAnnotatedName(Annotation[] annotations)
			throws ClassNotFoundException {
		if (annotations == null)
			return HasNoAnnotatedName;
		for (Annotation a : annotations) {
			if (a.annotationType() == AttributeNameAnnotation.class) {
				AttributeNameAnnotation ana = (AttributeNameAnnotation) a;
				return ana.Name();
			}
			if (a.annotationType() == EntityNameAnnotation.class) {
				EntityNameAnnotation ena = (EntityNameAnnotation) a;
				return ena.Name();
			}
			if (a.annotationType() == ValueObjectNameAnnotation.class) {
				ValueObjectNameAnnotation ena = (ValueObjectNameAnnotation) a;
				return ena.Name();
			}
		}
		return "HasNoAnnotatedName";
	}

	public static boolean isAgregator(Field f) {
		Annotation[] annotations = f.getAnnotations();
		if (annotations == null)
			return false;
		for (Annotation a : annotations) {
			if (a.annotationType() == AttributeNameAnnotation.class) {
				AttributeNameAnnotation ana = (AttributeNameAnnotation) a;
				return ana.isAggregator();
			}
		}
		return false;
	}

	public static String getAnnotatedGenericParameterType(Field f) {
		for (Annotation annotation : f.getAnnotations()) {
			if (annotation.annotationType() == AttributeNameAnnotation.class) {
				AttributeNameAnnotation attributeNameAnnotation = (AttributeNameAnnotation) annotation;
				return attributeNameAnnotation.genericParam();
			}
		}
		return null;
	}

	public static String getSourceTableName(Field f) {
		for (Annotation annotation : f.getAnnotations()) {
			if (annotation.annotationType() == AttributeNameAnnotation.class) {
				AttributeNameAnnotation attributeNameAnnotation = (AttributeNameAnnotation) annotation;
				return attributeNameAnnotation.sourceTableName();
			}
		}
		return null;
	}

	public static String getLinksTable(Field f) {
		for (Annotation annotation : f.getAnnotations()) {
			if (annotation.annotationType() == AttributeNameAnnotation.class) {
				AttributeNameAnnotation attributeNameAnnotation = (AttributeNameAnnotation) annotation;
				return attributeNameAnnotation.linksTable();
			}
		}
		return null;
	}

	public static Field[] getAllFields(Class inputClass) {
		List<Field> result = new ArrayList<Field>();
		result.addAll(Arrays.asList(inputClass.getDeclaredFields()));
		if (inputClass.getSuperclass() != null)
			result.addAll(Arrays.asList(getAllFields(inputClass.getSuperclass())));
		return (Field[]) result.toArray(new Field[0]);
	}

	public static String getValueListFromSimpleCollection(Collection collection) {
		String result = "";
		for (Object object : collection) {
			result += javaToOracleValuesConverter(object);
		}
		return result;
	}

	public static String javaToOracleValuesConverter(Object object) {
		String result = "";
		if (object == null)
			result = "null, ";
		else if (object.getClass().equals(String.class)
				|| Enum.class.isAssignableFrom(object.getClass())) {
			result += "'" + object + "', ";
		} else if (object.getClass().equals(Boolean.class)) {
			if (object.equals(false))
				result += "0, ";
			else
				result += "1, ";
		} else {
			result = object.toString() + ", ";
		}
		return result;
	}

	public static Connection getConnection() throws Exception {
		Class.forName("oracle.jdbc.driver.OracleDriver");
		return DriverManager.getConnection(
				"jdbc:oracle:thin:@localhost:1521:XE", "system", "sa");
	}
}
